package com.microservice.salmon.oauth.service.impl;

import com.microservice.salmon.db.entities.ShopMenu;
import com.microservice.salmon.db.entities.ShopRole;
import com.microservice.salmon.db.entities.ShopUser;
import com.microservice.salmon.db.entities.SysMenu;
import com.microservice.salmon.db.entities.SysRole;
import com.microservice.salmon.db.entities.SysUser;
import com.microservice.salmon.oauth.client.ClientInfo;
import com.microservice.salmon.oauth.client.ClientProcessorHolder;
import com.microservice.salmon.oauth.properties.SecurityProperties;
import com.microservice.salmon.oauth.service.rbac.ShopRbacService;
import com.microservice.salmon.oauth.service.rbac.SysRbacService;
import com.microservice.salmon.oauth.service.rbac.WebUserRbacService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * UserDetailsService 实现类，用于获取用户授权信息
 * </p>
 *
 * @author 王洪庆 2018-10-21 22:39
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private SysRbacService sysRbacService;

    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private ShopRbacService shopRbacService;

    @Autowired
    private WebUserRbacService webUserRbacService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //TODO 需要校验是否是手机号登录 如果是手机号登录 username存放的是手机号
        ClientInfo clientInfo = ClientProcessorHolder.getClientInfo();
        if (StringUtils.equals(clientInfo.getClientId(),securityProperties.getClient().getAdmin())) {
            // 如果是后台管理的客户端
            return buildAdminUserDetails(username, clientInfo);
        } else if (StringUtils.equals(clientInfo.getClientId(),securityProperties.getClient().getShop())) {
            // 店铺管理端
            return buildShopUserDetails(username, clientInfo);
        } else if (StringUtils.equals(clientInfo.getClientId(),securityProperties.getClient().getWeb())) {
            // web 端
            return buildWebUserDetails(username, clientInfo);
        } else { // 其他情况
            return buildWebUserDetails(username, clientInfo);
        }
    }


    private UserDetails buildAdminUserDetails(String username, ClientInfo clientInfo) {
        SysUser user = sysRbacService.getUserInfoByUsername(username);
        if(user == null) {
            throw new BadCredentialsException("用户不存在");
        }
        clientInfo.setRealName(user.getName());//记录当前登录用户的真实姓名
        clientInfo.setPhoto(user.getPhoto());//记录当前登录用户的头像
        // 记录用户
        boolean enabled = user.getDataFlag() == 1; // 可用性 :true:可用 false:不可用
        boolean accountNonExpired = true; // 用户期性 :true:没过期 false:过期
        boolean credentialsNonExpired = true; // 账号凭证是否未过期 :true:凭证有效 false:凭证无效
        boolean accountNonLocked = user.getUserStatus() == 1; // 锁定性 :true:未锁定 false:已锁定
        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
        // 根据具体的情况对用户的 可用性 过期性 有效性 锁定性 判断
        if(enabled && accountNonExpired && credentialsNonExpired && accountNonLocked) {
            List<SysRole> roleResult = sysRbacService.getRoleByUserId(user.getId());
            if (!CollectionUtils.isEmpty(roleResult)) {
                for (SysRole role : roleResult) {
                    //角色必须是ROLE_开头，可以在数据库中设置
                    if (StringUtils.isEmpty(role.getEnname())) {
                        continue;
                    }
                    GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_" + role.getEnname());
                    grantedAuthorities.add(grantedAuthority);
                    //获取权限
                    List<SysMenu> permissionList = sysRbacService.getMenuInfoByRoleId(role.getId());
                    if (!CollectionUtils.isEmpty(permissionList)) {
                        for (SysMenu menu : permissionList) {
                            if (StringUtils.isEmpty(menu.getHref())) {
                                continue;
                            }
                            GrantedAuthority authority = new SimpleGrantedAuthority(menu.getHref()); // 访问路径作为权限
                            grantedAuthorities.add(authority);
                        }
                    }
                }
            }
        }
        return new User(username, user.getPassword(),
                enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuthorities);
    }

    private UserDetails buildShopUserDetails(String username, ClientInfo clientInfo) {
        ShopUser user = shopRbacService.obtainShopUser(username);
        if(user == null) {
            throw new BadCredentialsException("用户不存在");
        }
        clientInfo.setUserId(user.getId());
        clientInfo.setRealName(user.getName());//记录当前登录用户的真实姓名
        clientInfo.setPhoto(user.getPhoto());//记录当前登录用户的头像
        clientInfo.setRoleId(user.getRoleId());
        clientInfo.setShopId(user.getShopId());
        // 记录用户
        boolean enabled = user.getDataFlag() == 1; // 可用性 :true:可用 false:不可用
        boolean accountNonLocked = user.getUserStatus() == 1; // 锁定性 :true:未锁定 false:已锁定

        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
        // 根据具体的情况对用户的 可用性 过期性 有效性 锁定性 判断
        if(enabled && accountNonLocked) {
            ShopRole shopRole = shopRbacService.obtainShopRoleByRoleId(user.getRoleId());
            if(shopRole != null) { // 约定角色id为0 为店铺超级管理员，此时shopRole == null
                //角色必须是ROLE_开头，可以在数据库中设置
                if (!StringUtils.isEmpty(shopRole.getEnname()) && shopRole.getDataFlag() == 1) {
                    GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_" + shopRole.getEnname());
                    grantedAuthorities.add(grantedAuthority);
                }
            }
            //获取权限,通过角色ID以及店铺ID来获取权限列表
            List<ShopMenu> permissionList = shopRbacService.obtainShopMenu(user.getRoleId(), user.getShopId());
            if (!CollectionUtils.isEmpty(permissionList)) { // 不为空
                for (ShopMenu menu : permissionList) {
                    if (StringUtils.isEmpty(menu.getHref())) { // 链接信息
                        continue;
                    }
                    GrantedAuthority authority = new SimpleGrantedAuthority(menu.getHref()); // 访问路径作为权限
                    grantedAuthorities.add(authority);
                }
            }
        }
        return new User(username, user.getPassword(),
                enabled, true, true, accountNonLocked, grantedAuthorities);
    }

    private UserDetails buildWebUserDetails(String username, ClientInfo clientInfo) {
        com.microservice.salmon.db.entities.User user = webUserRbacService.obtainUser(username);
        if(user == null) {
            throw new BadCredentialsException("用户不存在");
        }
        clientInfo.setRealName(user.getName());//记录当前登录用户的真实姓名
        clientInfo.setPhoto(user.getPhoto());//记录当前登录用户的头像
        clientInfo.setUserId(user.getId());
        return new User(username, user.getPassword(),
                user.getDataFlag() == 1, true, true,
                user.getUserStatus() == 1, AuthorityUtils.createAuthorityList("ROLE_USER"));
    }
}
